package com.atguigu.gmall.seckill.listener;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.mq.seckill.SeckillOrderMsg;
import com.atguigu.gmall.seckill.entity.SeckillGoods;
import com.atguigu.gmall.seckill.service.SeckillGoodsService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class SeckillOrderListener {

    @Autowired
    SeckillGoodsService seckillGoodsService;
    @Autowired
    StringRedisTemplate redisTemplate;

    //监听并创建 队列 seckill-order-queue
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(value = MqConst.SECKILL_ORDER_QUEUE,durable = "true",autoDelete = "false"),
                    exchange = @Exchange(value = MqConst.SECKILL_EVENT_EXCHANGE,durable = "true",autoDelete = "false",type = "topic"),
                    key = MqConst.SECKILL_ORDER_RK
            )
    })
    public void listen(Message message, Channel channel){
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        String content = new String(message.getBody());//消息体
        SeckillOrderMsg msg = JSON.parseObject(content, SeckillOrderMsg.class);
        //todo 下秒杀单
        log.info("秒杀排队：{}",msg);
        SeckillGoods detail = seckillGoodsService.getDetail(msg.getSkuId());
        try {
            //1数据库扣库存
            seckillGoodsService.deduceStock(detail.getId());
            //2临时保存一个秒杀单数据
            seckillGoodsService.saveSeckillOrder(msg);
            //3更新redis中的库存标识
            seckillGoodsService.updateRedisStock(msg);
            channel.basicAck(deliveryTag, false);

            log.info("用户：{}，商品：{}，秒杀成功",msg.getUserId(),msg.getSkuId());
        }catch (Exception e){
            //扣库存异常，说明库存灭有了
            //4给redis 一个占位符
            redisTemplate.opsForValue().set(RedisConst.SECKILL_ORDER+msg.getCode(), "X",2, TimeUnit.DAYS);

            log.info("\"用户：{}，商品：{}，秒杀失败",msg.getUserId(),msg.getSkuId());
        }
    }
}
